package com.illtamer.infinite.sillage.service;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.illtamer.infinite.sillage.exception.NotFoundException;
import com.illtamer.infinite.sillage.mapper.BlogMapper;
import com.illtamer.infinite.sillage.mapper.BlogTagMapper;
import com.illtamer.infinite.sillage.mapper.CommentMapper;
import com.illtamer.infinite.sillage.pojo.Blog;
import com.illtamer.infinite.sillage.util.MarkdownUtil;
import com.illtamer.infinite.sillage.util.TimeUtil;
import com.illtamer.infinite.sillage.vo.BlogQuery;
import com.illtamer.infinite.sillage.vo.HomeBlog;
import com.illtamer.infinite.sillage.vo.MinBlog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class BlogService extends BaseMapperService<Blog> {

    @Resource(name = "blogTagMapper")
    private BlogTagMapper blogTagMapper;

    @Resource(name = "commentMapper")
    private CommentMapper commentMapper;

    @Autowired
    public BlogService(BaseMapper<Blog> mapper) {
        super(mapper);
    }

    /**
     * 搜索展示文章 VO
     * */
    public Page<HomeBlog> searchHomeBlog(String content, Integer index) {
        return ((BlogMapper) mapper).searchHomeBlog(new Page<>(index, 10), content);
    }

    /**
     * 查询首页推荐文章 VO
     * */
    public Page<HomeBlog> listRecommendHomeBlog(Integer index) {
        return ((BlogMapper) mapper).listRecommendHomeBlog(new Page<>(index, 10));
    }

    /**
     * 查询首页展示文章 VO
     * */
    public Page<HomeBlog> listHomeBlogByTypeId(int currentPage, int limit, Integer typeId) {
        return ((BlogMapper) mapper).listHomeBlogByTypeId(new Page<>(currentPage, limit), typeId);
    }

    /**
     * 查询首页展示文章 VO
     * */
    public Page<HomeBlog> listHomeBlogByTagId(int index, int limit, Integer tagId) {
        return blogTagMapper.listHomeBlogByTagId(new Page<>(index, limit), tagId);
    }

    /**
     * 查询首页最新最简文章 VO
     * @apiNote Limit 10
     * */
    public List<MinBlog> listLatestMinBlog() {
        return ((BlogMapper) mapper).listLatestMinBlog(new Page<>(1, 10)).getRecords();
    }

    /**
     * 查询最简文章 VO
     */
    public Map<String, Map<String, List<MinBlog>>> listMinBlogOrderByYearWithMonth() {
        Map<String, Map<String, List<MinBlog>>> result = new TreeMap<>();
        BlogMapper mapper = (BlogMapper) this.mapper;
        for (String year : mapper.listYear()) {
            Map<String, List<MinBlog>> monthResult = mapper.listMinBlogByYear(year).stream()
                    .collect(Collectors.groupingBy(
                            minBlog -> TimeUtil.cutMonth(minBlog.getCreateTime())
                    ));
            result.put(year, monthResult);
        }
        return result;
    }

    /**
     * 级联新增 sillage_blog_tag
     * */
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertBlog(Blog blog) {
        final Boolean insertBlog = ((BlogMapper) mapper).insertBlog(blog);
        if (blog.getTags() == null) return insertBlog;
        return blogTagMapper.insertTagIdsByBlogId(blog.getId(), blog.getTags());
    }

    /**
     * 级联更新 sillage_blog_tag
     * */
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateBlog(Blog blog) {
        final Boolean updateBlog = ((BlogMapper) mapper).updateBlog(blog);
        if (blog.getTags() == null) return updateBlog;
        blogTagMapper.deleteTagIdsByBlogId(blog.getId());
        return blogTagMapper.insertTagIdsByBlogId(blog.getId(), blog.getTags());
    }

    @Transactional(rollbackFor = Exception.class)
    public Boolean updateViews(Long count, Integer blogId) {
        return ((BlogMapper) mapper).updateViews(count, blogId);
    }

    @Transactional(rollbackFor = Exception.class)
    public Blog selectById(int id) {
        return mapper.selectById(id);
    }

    @Transactional(rollbackFor = Exception.class)
    public Blog selectByIdAndConvert(int id) {
        final Blog blog = mapper.selectById(id);
        if (blog == null)
            throw new NotFoundException("Entity `Blog` with `id` " + id + " can not be found !");
        String content = MarkdownUtil.markdownToHtmlExt(blog.getContent());
        blog.setContent(content);
        return blog;
    }

    @Transactional(rollbackFor = Exception.class)
    public Page<Blog> listBlogs(int currentPage, int limit) {
        return listBlogs(null, currentPage, limit);
    }

    @Transactional(rollbackFor = Exception.class)
    public Page<Blog> listBlogs(BlogQuery blog, int currentPage, int limit) {
        return ((BlogMapper) mapper).listBlogs(new Page<>(currentPage, limit), blog);
    }

    public Boolean deleteById(Integer id) {
        boolean success = mapper.deleteById(id) > 0;
        if (success) {
            commentMapper.deleteByBlogId(id);
            blogTagMapper.deleteTagIdsByBlogId(id);
        }
        return success;
    }

}
